import Konva from 'konva'
import { useRef, useState } from 'react'
import { Group, Layer, Line, Stage, Transformer } from 'react-konva'

export default function View() {
  // pen
  const [tool, setTool] = useState('pen')
  const [lines, setLines] = useState([])
  const isDrawing = useRef(false)
  const groupRef = useRef<Konva.Group>(null)

  const handleMouseDown = e => {
    isDrawing.current = true
    const pos = e.target.getStage().getPointerPosition()
    setLines([
      ...lines,
      { tool, points: [pos.x, pos.y], x: 0, y: 0, scaleX: 1, scaleY: 1, skewX: 0, skewY: 0, rotation: 0 }
    ])
  }

  const handleMouseMove = e => {
    if (!isDrawing.current) {
      return
    }
    const stage = e.target.getStage()
    const point = stage.getPointerPosition()
    const lastLine = lines[lines.length - 1]
    lastLine.points = lastLine.points.concat([point.x, point.y])
    lines.splice(lines.length - 1, 1, lastLine)
    setLines(lines.concat())
  }

  const handleMouseUp = () => {
    isDrawing.current = false
  }

  // transform
  const [selectedShape, setSelectedShape] = useState(null)
  const transformerRef = useRef(null)
  const handleStageClick = e => {
    // clear
    if (e.target === e.target.getStage()) {
      setSelectedShape(null)
      return
    }
    if (e.target.nodeType === 'Shape') {
      setSelectedShape(groupRef.current)
    }
  }
  // Find the rotated coordinates
  const rotatePoint = (x: number, y: number, theta: number) => {
    const radians = theta * (Math.PI / 180)
    const xNew = x * Math.cos(radians) - y * Math.sin(radians)
    const yNew = x * Math.sin(radians) + y * Math.cos(radians)

    return { x: xNew, y: yNew }
  }

  return (
    <div>
      <select
        value={tool}
        onChange={e => {
          setTool(e.target.value)
        }}
      >
        <option value='pen'>Pen</option>
        <option value='eraser'>Eraser</option>
      </select>
      <Stage
        width={window.innerWidth}
        height={window.innerHeight}
        onMouseDown={handleMouseDown}
        onMousemove={handleMouseMove}
        onMouseup={handleMouseUp}
        onClick={handleStageClick}
      >
        <Layer>
          <Group
            ref={groupRef}
            draggable
            onDragEnd={e => {
              // debugger
              const node = e.target
              const { x, y } = node.position()

              lines.forEach((_, index: number, array) => {
                array[index].x = array[index].x + x
                array[index].y = array[index].y + y
              })
              setLines(lines.concat())

              e.target.position({ x: 0, y: 0 })
              e.target.getLayer().batchDraw()
            }}
            onTransformEnd={e => {
              const node = e.target
              const { x, y } = node.position()
              const { x: scaleX, y: scaleY } = node.scale() || { x: 1, y: 1 }
              const { x: skewX, y: skewY } = node.skew()
              const rotation = node.rotation()

              console.log(
                'x:' + x,
                'y:' + y,
                'scaleX:' + scaleX,
                'scaleY:' + scaleY,
                'skewX:' + skewX,
                'skewY:' + skewY,
                'rotation:' + rotation
              )

              lines.forEach((_, index: number, array) => {
                const { x: lastX, y: lastY } = rotatePoint(array[index].x, array[index].y, rotation)
                array[index].x = lastX * scaleX + x
                array[index].y = lastY * scaleY + y

                array[index].scaleX = array[index].scaleX * scaleX
                array[index].scaleY = array[index].scaleY * scaleY
                if (skewX !== 0) {
                  array[index].skewX = array[index].skewX + skewX
                }
                if (skewY !== 0) {
                  array[index].skewY = array[index].skewY + skewY
                }
                const rawRotation = array[index].rotation + rotation
                if (rawRotation > 180) {
                  array[index].rotation = rawRotation - 360
                } else if (rawRotation < -180) {
                  array[index].rotation = rawRotation + 360
                } else {
                  array[index].rotation = rawRotation
                }
              })
              setLines(lines.concat())

              node.position({ x: 0, y: 0 }).scale({ x: 1, y: 1 }).skew({ x: 0, y: 0 }).rotation(0)
              node.getLayer()?.batchDraw()
            }}
          >
            {lines.map((line, i) => (
              <Line
                key={i}
                x={line.x}
                y={line.y}
                scaleX={line.scaleX}
                scaleY={line.scaleY}
                skewX={line.skewX}
                skewY={line.skewY}
                // rotation={line.rotation}
                points={line.points}
                stroke='#df4b26'
                strokeWidth={10}
                tension={0.5}
                lineCap='round'
                lineJoin='round'
                globalCompositeOperation={line.tool === 'eraser' ? 'destination-out' : 'source-over'}
              />
            ))}
          </Group>
          {selectedShape && (
            <Transformer
              // rotateEnabled={false}
              ref={transformerRef}
              enabledAnchors={['top-left', 'top-right', 'bottom-left', 'bottom-right']}
              boundBoxFunc={(oldBox, newBox) => {
                if (newBox.width < 5 || newBox.height < 5) {
                  return oldBox
                }
                return newBox
              }}
              nodes={[selectedShape]}
            />
          )}
        </Layer>
      </Stage>
    </div>
  )
}
